import Router from 'koa-router';
import assert from 'assert';
import { isEmpty } from 'lodash';
import User from '../models/user';
import ChannelUser from '../models/channelUser';
import Group from '../models/group';
import Channel from '../models/channel';
import tokenAuth from '../middleware/tokenAuth';

import {
  USER_GROUP_ADMIN,
  USER_GROUP_STUDENT_ASSIST,
  USER_GROUP_TEACHER_ASSIST,
  USER_GROUP_TEACHER_TRAINER,
  USER_GROUP_TECH_SUPPORT,
} from '../common/groups';

import channelHandler from '../handler/channelHandlers';

const router = new Router({
  prefix: '/api/users',
});

router.post('/logout', tokenAuth(), async (ctx) => {
  const channels = await Channel.find({ members: ctx.viewer }).exists('customer');
  if (channels && !isEmpty(channels)) {
    for (const channel of channels) {
      await channelHandler.leave(channel, ctx.viewer);
    }
  }
  ctx.body = {
    ok: true,
  };
});

router.post('/admins', tokenAuth(), async (ctx) => {
  const { creator } = ctx.request.body;

  if (!creator) {
    ctx.throw('no_creator');
  }

  const user = await User.findById(creator).populate('group');
  if (!user) {
    ctx.throw('user_not_exist');
  }

  let groups = [];
  // 如果是客户组，获取responseGroups
  if (user.group.isCustomer) {
    groups = await Group.find({ responseGroups: { $in: [user.group] } });
  } else {
    groups = await Group.find({ isCustomer: false });
  }

  const admins = [];

  if (groups) {
    const groupAdmins = await User.find({
      group: { $in: groups.map(group => group._id) },
    });
    if (groupAdmins) {
      groupAdmins.map(admin =>
        admins.push({
          id: admin._id,
          name: admin.username,
        }));
    }
  }

  ctx.body = {
    ok: true,
    admins,
  };
});

router.post('/assistants', tokenAuth(), async (ctx) => {
  const groups = await Group.find({
    name: {
      $in: [
        USER_GROUP_ADMIN,
        USER_GROUP_STUDENT_ASSIST,
        USER_GROUP_TEACHER_ASSIST,
        USER_GROUP_TEACHER_TRAINER,
        USER_GROUP_TECH_SUPPORT,
      ],
    },
  });
  const assistants = await User.find({ group: { $in: groups } });
  ctx.body = {
    ok: true,
    assistants: assistants.map(assistant => ({
      id: assistant._id.toString(),
      name: assistant.username,
    })),
  };
});

router.post('/filter', tokenAuth(), async (ctx) => {
  const { filter } = ctx.request.body;
  let { group } = ctx.request.body;
  let channels = [];
  if (filter) {
    group = await Group.findOne({ name: group });
    const adminGroup = await Group.findOne({
      _id: ctx.viewer.group,
      responseGroups: { $in: [group] },
    });
    channels = [];
    if (adminGroup) {
      const _filter = { $regex: filter, $options: '$i' };
      // 精确查找JiuquId
      let users;
      if (/^@\d+$/.test(filter)) {
        const jiuquId = filter.replace('@', '');
        users = await User.find({
          jiuquId: { $regex: `Student:${jiuquId}$|Teacher:${jiuquId}$` },
          group,
        });
      } else {
        users = await User.find({
          $or: [{ username: _filter }, { nickname: _filter }, { mobile: _filter }],
          group,
        });
      }

      channels = await Channel.find({ customer: { $in: users } });
      channels = channels.map(channel => ({
        id: channel._id,
        name: channel.name,
        isPrivate: channel.isPrivate,
      }));
    }
  }

  ctx.body = {
    ok: true,
    filter,
    channels,
  };
});

router.post('/onlineUsers', tokenAuth(), async (ctx) => {
  const { redis } = ctx;

  const [onlineUsers, onlineJanus, onlineSkynet] = await Promise.all([
    await redis.hgetall('user:online'),
    await redis.hgetall('teacher:online:janus'),
    await redis.hgetall('teacher:online:skynet'),
  ]);

  ctx.body = {
    ok: true,
    onlineUsers,
    onlineJanus,
    onlineSkynet,
  };
});

router.post('/userByJiuquId', tokenAuth(), async (ctx) => {
  const { jiuquId } = ctx.request.body;
  assert(jiuquId, 'jiuquId_not_exist');

  const user = await User.findOne({ jiuquId });

  ctx.body = {
    ok: true,
    user,
  };
});

router.post('/userByJiuquIds', tokenAuth(), async (ctx) => {
  const { jiuquIds } = ctx.request.body;
  assert(jiuquIds, 'jiuquId_not_exist');

  const users = await User.find({ jiuquId: jiuquIds });
  const userObjectIds = users.map(u => u.id);
  const channelUsers = await ChannelUser.find({ user: userObjectIds }).populate('user');
  const finalUsers = channelUsers
    .map(cu => Object.assign({ lastActiveAt: cu.lastActiveAt }, cu.toJSON().user));

  ctx.body = {
    ok: true,
    users: finalUsers,
  };
});

router.put('/refresh/headImgUrl', tokenAuth(), async (ctx) => {
  const { headImgUrl } = ctx.request.body;
  const { viewer } = ctx;

  if (!headImgUrl) {
    ctx.throw('empty_img');
  }

  viewer.headImgUrl = headImgUrl;
  await viewer.save();

  ctx.body = {
    ok: true,
  };
});

export default router;
